package com.ddstation.app.doctor_verify.service;

import com.ddstation.app.doctor_verify.mapper.AppDoctorVerifyMapper;
import com.ddstation.app.doctor_verify.model.AppDoctorVerifyModel;
import com.ddstation.common.entity.DdPictureEntity;
import com.ddstation.common.face_api.AipFaceUtil;
import com.ddstation.common.mapper.DdPictureMapper;
import com.ddstation.common.model.ImageModel;
import com.ddstation.common.util.AliCloudOssUtil;
import com.ddstation.doctor.entity.DdDoctorEntity;
import com.ddstation.doctor.mapper.DdDoctorMapper;
import com.ddstation.security.util.MD5Util;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.inject.Inject;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Service @Lazy
public class AppDoctorVerifyServiceImpl implements AppDoctorVerifyService {
	private static final Logger log = LoggerFactory.getLogger(AppDoctorVerifyServiceImpl.class);

	@Inject private AppDoctorVerifyMapper appDoctorVerifyMapper;
	@Inject private DdDoctorMapper ddDoctorMapper;
	@Inject private DdPictureMapper ddPictureMapper;

	@Override
	public int saveLogId(String institutionId,Integer doctorId,String token,Long logId) {
		return appDoctorVerifyMapper.insert(institutionId,doctorId,token,String.valueOf(logId));
	}
	@Override
	public int selectCnt(String token) {
		return appDoctorVerifyMapper.selectCnt(token);
	}
	@Override
	public int updateStatus(String token) {
		return appDoctorVerifyMapper.updateStatus(token);
	}
	@Override
	public int updateDoctorInfo(DdDoctorEntity doctor, String institutionId) {
		return appDoctorVerifyMapper.updateDoctorInfo(doctor,institutionId);
	}
    @Override
    public int updateLogByToken(String token,Integer doctorId, String institutionId) {
        return appDoctorVerifyMapper.updateLogByToken(token,doctorId,institutionId);
    }

	public String imgCompress(String base64Img) {
		String resultImg = "";
		BASE64Encoder encoder = new BASE64Encoder();
		try {
			BASE64Decoder decoder = new BASE64Decoder();
			byte[] bytes = decoder.decodeBuffer(base64Img);
			ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
			int widthdist = 100;
			int heightdist = 100;
			Float rate = 0.3F;

			BufferedImage src = null;
			// 如果比例不为空则说明是按比例压缩
			if (rate != null && rate > 0) {
				//获得源图片的宽高存入数组中
				int result[] = { 0, 0 };
				try {
					src = ImageIO.read(bais);
					result[0] =src.getWidth(null); // 得到源图片宽
					result[1] =src.getHeight(null);// 得到源图片高
				} catch (Exception ef) {
					ef.printStackTrace();
				}

				int[] results = result;
				if (results == null || results[0] == 0 || results[1] == 0) {
					//return;
				} else {
					//按比例缩放或扩大图片大小，将浮点型转为整型
					widthdist = (int) (results[0] * rate);
					heightdist = (int) (results[1] * rate);
				}
			}
			// 构造一个类型为预定义图像类型之一的 BufferedImage
			BufferedImage tag = new BufferedImage((int) widthdist, (int) heightdist, BufferedImage.TYPE_INT_RGB);

			//绘制图像  getScaledInstance表示创建此图像的缩放版本，返回一个新的缩放版本Image,按指定的width,height呈现图像
			//Image.SCALE_SMOOTH,选择图像平滑度比缩放速度具有更高优先级的图像缩放算法。
			tag.getGraphics().drawImage(src.getScaledInstance(widthdist, heightdist, Image.SCALE_SMOOTH), 0, 0, null);

			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ImageIO.write(tag, "jpg", baos);
			byte[] bytes1 = baos.toByteArray();
			resultImg = encoder.encodeBuffer(bytes1).trim();

			Integer size3_1=resultImg.length()-(resultImg.length()/8)*2;
			log.info("压缩后大小:" + size3_1);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return resultImg;
	}

	@Override
	public Map<String, Object> doVerify(String institutionId, Integer doctorId, String baseImg1, String baseImg2, String baseImg3,String name,String idCard) {
		Map<String, Object> retMap = new HashMap<String, Object>();
		log.info("开始进行人脸识别");
		Integer size1=baseImg1.length()-(baseImg1.length()/8)*2;
		log.info("图片大小1:" + size1);
		Integer size2=baseImg2.length()-(baseImg2.length()/8)*2;
		log.info("图片大小2:" + size2);
		Integer size3=baseImg3.length()-(baseImg3.length()/8)*2;
		log.info("图片大小3:" + size3);
		if (size1 >= 2 * 1024 * 1024) {    //大于2M
			log.info("原始1：" + baseImg1);
			baseImg1 = this.imgCompress(baseImg1);
			log.info("压缩1：" + baseImg1);
        }
		if (size2 >= 2 * 1024 * 1024) {    //大于2M
			log.info("原始2：" + baseImg2);
			baseImg2 = this.imgCompress(baseImg2);
			log.info("压缩2：" + baseImg2);
		}
		if (size3 >= 2 * 1024 * 1024) {    //大于2M
			log.info("原始2：" + baseImg3);
			baseImg3 = this.imgCompress(baseImg3);
			log.info("压缩3：" + baseImg3);
		}

//		BASE64Decoder decoder = new BASE64Decoder();
//		try {
//			// 解密
//			byte[] b = decoder.decodeBuffer(baseImg3);
//			// 处理数据
//			for (int i = 0; i < b.length; ++i) {
//				if (b[i] < 0) {
//					b[i] += 256;
//				}
//			}
//			OutputStream out = new FileOutputStream("/Users/longer/Desktop/1s.jpg");
//			out.write(b);
//			out.flush();
//			out.close();
//		} catch (Exception e) {
//		}

		JSONObject idCardsJson1 = AipFaceUtil.idcardByBase64Img(baseImg1,"front");
		log.info(idCardsJson1.toString());
		if (idCardsJson1 != null && "normal".equals(idCardsJson1.getString("image_status"))) {
			JSONObject wordsResult = idCardsJson1.getJSONObject("words_result");
			JSONObject nameJson = wordsResult.getJSONObject("姓名");
			JSONObject idCardJson = wordsResult.getJSONObject("公民身份号码");
			String name2 = nameJson.getString("words");
			String idCard2 = idCardJson.getString("words");
			if (name2!=null && !name2.equals(name)) {
				retMap.put("errorMsg", "身份证姓名不匹配");
				return retMap;
			}
			if (idCard2!=null && !idCard2.equals(idCard)) {
				retMap.put("errorMsg", "身份证号码不匹配");
				return retMap;
			}
			retMap.put("name", name2);
			retMap.put("idCard", idCard2);
		} else if (idCardsJson1 != null && !"normal".equals(idCardsJson1.getString("image_status"))) {
			String image_status = idCardsJson1.getString("image_status");
			if ("reversed_side".equals(image_status)) {
				retMap.put("errorMsg", "未摆正正面身份证");
			} else if ("non_idcard".equals(image_status)) {
				retMap.put("errorMsg", "上传的正面图片中不包含身份证");
			} else if ("blurred".equals(image_status)) {
				retMap.put("errorMsg", "身份证正面模糊");
			} else if ("over_exposure".equals(image_status)) {
				retMap.put("errorMsg", "身份证正面关键字段反光或过曝");
			} else if ("unknown".equals(image_status)) {
				retMap.put("errorMsg", "身份证正面识别未知状态");
			} else {
				retMap.put("errorMsg", "身份证正面识别失败");
			}
			return retMap;
		} else {
			retMap.put("errorMsg", "正面身份证识别失败");
			return retMap;
		}

		JSONObject idCardsJson2 = AipFaceUtil.idcardByBase64Img(baseImg2,"back");
		log.info(idCardsJson2.toString());
		if (idCardsJson2 != null && "normal".equals(idCardsJson2.getString("image_status"))) {

		} else if (idCardsJson2 != null && !"normal".equals(idCardsJson2.getString("image_status"))) {
			String image_status = idCardsJson2.getString("image_status");
			if ("reversed_side".equals(image_status)) {
				retMap.put("errorMsg", "未摆正反面身份证");
			} else if ("non_idcard".equals(image_status)) {
				retMap.put("errorMsg", "上传的反面图片中不包含身份证");
			} else if ("blurred".equals(image_status)) {
				retMap.put("errorMsg", "身份证反面模糊");
			} else if ("over_exposure".equals(image_status)) {
				retMap.put("errorMsg", "身份证反面关键字段反光或过曝");
			} else if ("unknown".equals(image_status)) {
				retMap.put("errorMsg", "身份证反面识别未知状态");
			} else {
				retMap.put("errorMsg", "身份证反面识别失败");
			}
			return retMap;
		} else {
			retMap.put("errorMsg", "反面身份证识别失败");
			return retMap;
		}
		JSONObject json1 = AipFaceUtil.faceContrastByBase64Img(baseImg1,baseImg3);
		log.info(json1.toString());
		if (json1 != null && "SUCCESS".equals(json1.getString("error_msg"))) {
			Long log_id = json1.getLong("log_id");
			JSONObject result = json1.getJSONObject("result");
			double score = result.getDouble("score");
			if (score >= 70) {
				retMap.put("errCode", 0);
				retMap.put("errorMsg", "");
				String token = "";
				try {
					token = MD5Util.md5Encode(String.valueOf(log_id) + baseImg1 + baseImg3);
				} catch (Exception e) {
				}
				log.info("认证成功！logId = " + log_id + " token = " + token + " institutionId = " + institutionId + " doctorId = " + doctorId);
				if (this.saveLogId(institutionId,doctorId,token, log_id) == 1) {
					retMap.put("token", token);
				} else {
					retMap.put("errorMsg", "系统繁忙，请稍后再试");
				}
			} else {
				retMap.put("errorMsg", "认证失败，请重新上传身份证");
			}
		} else if (json1 != null && "pic not has face".equals(json1.getString("error_msg"))) {
			retMap.put("errorMsg", "未检测到身份证，请重新上传");
			log.info("人脸1：" + baseImg1);
			log.info("人脸2：" + baseImg3);
		} else {
			retMap.put("errorMsg", "认证失败，请重新上传身份证");
			log.info("人脸1：" + baseImg1);
			log.info("人脸2：" + baseImg3);
		}
		log.info("结束人脸识别");
		return retMap;
	}

	@Override
	public Map<String, Object> doVerifyLogin(String institutionId, Integer doctorId, String token, String baseImg) {
		Map<String, Object> retMap = new HashMap<String, Object>();
		log.info("开始进行人脸识别");
		AppDoctorVerifyModel model = appDoctorVerifyMapper.selectByToken(token);
		if (model != null && model.getDoctorId() != null && model.getDoctorId().intValue() != doctorId.intValue()) {
            retMap.put("errorMsg","App与网站登录账户不一致");
            return retMap;
        } else if (model != null && model.getLogId() == null) {
			DdDoctorEntity entity = ddDoctorMapper.selectDoctorInfo(model.getDoctorId().toString());
			if (entity.getDoctorVerifySt() != 20) {
				retMap.put("errorMsg","未进行身份资质备案");
				return retMap;
			}
			if (entity.getIdCardAtta() == null) {
				retMap.put("errorMsg","无身份证信息");
				return retMap;
			}
			// 获取身份证正面
			String sid =entity.getIdCardAtta().split(",")[0];
			DdPictureEntity pictureEntity = ddPictureMapper.selectOne(sid);
			ImageModel image = new ImageModel();
			image.setId(Integer.parseInt(entity.getId()));
			image.setObjKey(pictureEntity.getPath());
			String baseImg1 =AipFaceUtil.ImageToBase64ByOnline(AliCloudOssUtil.getOriginImgUrl(null, pictureEntity.getPath()));
			JSONObject json1 = AipFaceUtil.faceContrastByBase64Img(baseImg1,baseImg);
			log.info(json1.toString());
			if (json1 != null && "SUCCESS".equals(json1.getString("error_msg"))) {
				Long log_id = json1.getLong("log_id");
				JSONObject result = json1.getJSONObject("result");
				double score = result.getDouble("score");
				if (score >= 70) {
					retMap.put("errorMsg", "");
					log.info("认证成功！logId = " + log_id + " token = " + token + " institutionId = " + institutionId + " doctorId = " + doctorId);
					if (appDoctorVerifyMapper.updateLogId(token, log_id) == 1) {
						retMap.put("errCode", 0);
					} else {
						retMap.put("errorMsg", "系统繁忙，请稍后再试");
					}
				} else {
					retMap.put("errorMsg", "认证失败，请重新认证");
				}
			} else if (json1 != null && "pic not has face".equals(json1.getString("error_msg"))) {
				retMap.put("errorMsg", "未检测到身份证，请重新上传");
			} else {
				retMap.put("errorMsg", "认证失败，请重新认证");
			}
		}

		log.info("结束人脸识别");
		return retMap;
	}
}
